package com.asa.tongji;

import java.util.Arrays;

import com.asa.suanfa.SUtils;

public class TUtils4 {
	/********************检验统计10*************************/
	/**
	 * 总体比例的假设检验
	 * 要求：
	 * 1，样本是一个简单随机样本
	 * 2，满足二项分布的条件
	 * 3，满足np>=5,nq>=5
	 * @param p	估计概率值
	 * @param p1	实际概率值
	 * @param n	抽取样本数量
	 * @param a 置信度 百分比即可
	 * @return	这里利用零假设，要使用拒绝零假设的方式来判断，true为不能拒绝零假设
	 */
	public static boolean jiashejianyan(double p,double p1,int n,double a){
		double q = 1-p;
		double z = (p1 - p)/Math.sqrt(p*q/n);//计算检验统计量的值
		a = FenBuFunction.zhengtai(a);
		return z<a;
	}

	
	
	
	
	/**
	 * 总体均值的假设检验（方差已知）
	 * 要求：
	 * 1，样本是简单随机样本
	 * 2，总体标准差已知
	 * 3，总体是正态分布或n>30
	 * 
	 * @param o样本方差，如果未知总体，可以用样本中方差来替代
	 * @param ux	声明的平均值
	 * @param x1	样本计算得出的平均值
	 * @param n	样本数量
	 * @param a	正态分布，由置信度确定
	 * @return	true为不能拒绝零假设
	 */

	public static boolean junzhijianyan(double o,double ux,double x1,int n,double a){
		double z = (x1-ux)/Math.sqrt(o/n);
		a = FenBuFunction.zhengtai(a);
		return z<a;
	}
	/**
	 * 总体均值的假设检验（方差未知）
	 * 要求：
	 * 1，样本是简单随机样本
	 * 2，总体标准差已知
	 * 3，总体是正态分布或n>30
	 * 
	 * @param o样本方差，如果未知总体，可以用样本中方差来替代
	 * @param ux	声明的平均值
	 * @param x1	样本计算得出的平均值
	 * @param n	样本数量
	 * @param t	t分布，由置信度和样本数量n-1确定
	 * @return	true为不能拒绝零假设
	 */

	public static boolean junzhijianyanwuzongtifangcha(double o,double ux,double x1,int n,double t){
		double z = (x1-ux)/Math.sqrt(o/n);
		t = FenBuFunction.tfengbu(t, n-1);
		return z<t;
	}

	
	/**
	 * 总体方差的假设检验
	 * @param n	样本数量
	 * @param o1	样本方差
	 * @param o	声明标准差
	 * @param xx	卡方分布，计算值置信度和样本数量，去查表
	 * @return true为不能拒绝零假设
	 * @throws Exception 
	 */
	public static boolean fangchajianyan(int n,double o1,double o,double xx) throws Exception{
		double X = (n-1)*o1/o;//卡方分布
		xx = FenBuFunction.kafangfengbu(xx, n)[1];
		//System.out.println(X+"          "+xx);
		return X<xx;
	}
	

	
	

	/**
	 * 两个独立总体比例的比较
	 * 要求：
	 * 1，两个样本为相互独立的简单随机样本
	 * 2，对于每个样本，成功个数和失败个数都要大于等于5
	 * 
	 * @param x1	符合样本数量
	 * @param x2	符合样本数量
	 * @param p1	声明样本比例。或者说是概率
	 * @param p2	声明样本比例。或者说是概率
	 * @param n1	样本总体数量
	 * @param n2	样本总体数量
	 * @param a	置信度
	 * @return true为不能拒绝零假设，没有差别，检验两个总体比例是否相等
	 */

	public static boolean zongtibilijianyan(int x1,int x2,double p1,double p2,int n1,int n2,double a){
		a = FenBuFunction.zhengtai(a);
		double p1hat = (double)x1/(double)n1;
		double p2hat = (double)x2/(double)n2;
		double phat = (double)(x1+x2)/(double)(n1+n2);
		double qhat = 1-phat;
		double z = ((p1hat - p2hat)-(p1-p2))/Math.sqrt(phat*qhat/n1+phat*qhat/n2);
		return z<a;
	}
	
	
	
	/**
	 * 两个独立总体均值的比较
	 * 要求
	 * 1，两个独立样本的总体标准差已知
	 * 2，两个样本相互独立
	 * 3，两个样本都是简单随机样本
	 * 4，两个样本的总体服从正态分布或是样本容量n1>30,n2>30
	 * @param x1	样本均值
	 * @param x2	样本均值
	 * @param u1	声明样本均值
	 * @param u2	声明样本均值
	 * @param n1	样本数
	 * @param n2	样本数
	 * @param o1	方差
	 * @param o2	方差
	 * @param a	置信度得出的。。。这个是正态分布的
	 * @return	返回时否拒绝零假设，true为不能拒绝零假设,没有差别
	 */
	
	public static boolean liangjunzhijianyan(double x1,double x2,double u1,double u2,int n1,int n2,double o1,double o2,double a){
		a = FenBuFunction.zhengtai(a);
		double z = Math.abs((x1-x2)-(u1-u2))/Math.sqrt(o1/n1+o2/n2);
		//System.out.println(a+"      "+z);
		return z<a;
	}
	

	
	
	
	
	
	
	/**
	 * 两个独立总体均值的比较（总体标准差未知，但认为他们相等）
	 * 要求
	 * 1，两个独立样本的总体标准差未知，但认为他们相等
	 * 2，两个样本相互独立
	 * 3，两个样本都是简单随机样本
	 * 4，两个样本的总体服从正态分布或是样本容量n1>30,n2>30
	 * @param x1	样本均值
	 * @param x2	样本均值
	 * @param u1	声明样本均值
	 * @param u2	声明样本均值
	 * @param n1	样本数
	 * @param n2	样本数
	 * @param o1	根据样本得出的方差
	 * @param o2	根据样本得出的方差
	 * @param t	置信度得出的。。。这个是t分布的t(n1+n2-2)
	 * @return	返回时否拒绝零假设，true为不能拒绝零假设，即没有差别
	 */
	
	public static boolean liangjunzhijianyan2(double x1,double x2,double u1,double u2,int n1,int n2,double o1,double o2,double t){
		t = FenBuFunction.tfengbu(t, n1+n2-2);
		double sp2 = ((n1-1)*o1+(n2-1)*o2)/((n1-1)+(n2-1));
		double z = Math.abs((x1-x2)-(u1-u2))/Math.sqrt(sp2/n1+sp2/n2);
		//System.out.println(z+"        "+t);
		return z<t;
	}
	

	
	
	/**
	 * 两个独立总体均值的比较（两个独立样本的总体标准差未知，且认为他们不相等）
	 * 要求
	 * 1，两个独立样本的总体标准差未知，且认为他们不相等
	 * 2，两个样本相互独立
	 * 3，两个样本都是简单随机样本
	 * 4，两个样本的总体服从正态分布或是样本容量n1>30,n2>30
	 * @param x1	样本均值
	 * @param x2	样本均值
	 * @param u1	声明样本均值
	 * @param u2	声明样本均值
	 * @param n1	样本数
	 * @param n2	样本数
	 * @param o1	根据样本得出的方差
	 * @param o2	根据样本得出的方差
	 * @param t	置信度得出的。。。这个是t分布的t(v),其中v是n1-1和n2-1中小的那个
	 * @return	返回时否拒绝零假设，true为不能拒绝零假设
	 */
	
	public static boolean liangjunzhijianyan3(double x1,double x2,double u1,double u2,int n1,int n2,double o1,double o2,double t){
		//这个v是用来确定t的，t(v)中的v也可以取近似值，n1-1和n2-1中小的那个,这个叫自由度
		double v = Math.pow(o1/n1+o2/n2, 2)/(Math.pow(o1/n1, 2)/n1+Math.pow(o2/n2, 2)/n2);
//		v= 42;
		//System.out.println(v);
		t = FenBuFunction.tfengbu(t, v);
		double z = ((x1-x2)-(u1-u2))/Math.sqrt(o1/n1+o2/n2);
		//System.out.println(z+"        "+t);
		return z<t;
	}
	
	
	
	
	
	/**
	 * 配对样本t检验
	 * 主要是分享两样本间的拟合程度的
	 * 要求：
	 * 1，两个样本数据时配对样本
	 * 2，样本是简单随机样本
	 * 3，配对样本数据量足够大（大于30对数据）或配对样本数据插值的总体服从或近似服从正态分布
	 * @param t	t(n-1)
	 * @param d	样本差值的均值
	 * @param ud	差值的总体均值
	 * @param sd	样本差值的标准差
	 * @param n	配对数据的对数
	 * @return
	 */
	
	public static boolean peiduiyangben(double t,double d,double ud,double sd,double n){
		double z = (d - ud)/(sd/Math.sqrt(n));
		t = FenBuFunction.tfengbu(t, n);
		//System.out.println(z+"        "+t);
		return z<t;
	}
	

	
	
	
	
	/**
	 * 两个独立总体方差的比较
	 * 要求：
	 * 1，两个总体相互独立
	 * 2，两个总体服从正态分布
	 * 3，样本是简单随机样本
	 * 
	 * f(0.05,40,30)
	 * @param f	f分布
	 * @param s1	数据方差
	 * @param s2	数据方差
	 * @return	样本数据太大，f分布函数拟合有问题
	 * @throws Exception 
	 */

	public static boolean fangchabijiao(double f,double s1,double s2,int n1,int n2) throws Exception{
		double z;
		if (s1>s2) {
			z = (s1*s1)/(s2*s2);
		}else{
			z = (s2*s2)/(s1*s1);
		}
		f = FenBuFunction.ffengbu(f, n1,n2)[1];
		//System.out.println(z+"++++++++++++++++++"+f);
		return z<f;
	}
	

	
	
	/******************************11非参数方法，反正这不是主流的，随便了解一下吧***********************************/
	

	/**
	 * 符号检验	具体细节通被隐藏了
	 * 要求：
	 * 1，样本是简单随机样本
	 * 2，对总体分布形式不做任何要求
	 * 
	 * B~B(n,0.5)
	 * @param v	中位数
	 * @param x	样本
	 * @param point	
	 * @param z	
	 * @return
	 */
	@Deprecated
	public static double fuhaojianyan(double v,double[] x,double point,double z){
		
		int a=0,b=0,c=0;
		
		for (int i = 0; i < x.length; i++) {
			if (x[i]>v) {
				a++;
			}else if(x[i]<v){
				c++;
			}else{
				b++;
			}
		}
		
		int one = a;
		int two = a+c;
		
		
		
//		pbinom(23,91,0.5);
		//pnorm(-4.61)
		
		return 0;
	}
	
	/**
	 * 秩检验
	 * 把样本数据糅杂到以一起，要求a、b的长度大于10
	 * @param a	对照实验结果
	 * @param b	实验结果
	 * @return true为拒绝
	 * double[] a = {7.0,3.5,9.6,8.1,6.2,5.1,10.4,4.0,2.0,10.5};
		double[] b = {5.7,3.2,4.2,11.0,9.7,6.9,3.6,4.8,5.6,8.4,10.1,5.5,12.3};
		yangbenduibi(a, b, 0.95);
	 */
	public static boolean yangbenduibi(double[] a,double[] b,double asa){
		double[] x = new double[a.length+b.length];
		for (int i = 0; i < a.length; i++) {
			x[i] = a[i];
		}
		for (int i = 0; i < b.length; i++) {
			x[i+a.length] = b[i];
		}
		SUtils.bubble_2(x,x.length);
		//System.out.println(Arrays.toString(x));
		double na=0;
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < x.length; j++) {
				if (a[i] == x[j]) {
					int temp = j+1;
					while (true) {//为了解决节的问题
						if (temp==x.length) {
							temp--;
							double gall = 0;
							for (int k = j; k <= temp; k++) {
								gall+=k;
							}
							na = na+(double)(gall)/(temp-j+1)+1;
							
							break;
						}
						if (x[temp]==x[j]) {
							temp++;
						}else{
							temp--;
							double gall = 0;
							for (int k = j; k <= temp; k++) {
								gall+=k;
							}
							na = na+(double)(gall)/(temp-j+1)+1;
							//System.out.println(na);
							break;
						}
					}
					break;
				}
			}
		}
		double nb=0;
		for (int i = 0; i < b.length; i++) {
			for (int j = 0; j < x.length; j++) {
				if (b[i] == x[j]) {
					int temp = j+1;
					while (true) {//为了解决节的问题
						if (temp==x.length) {
							temp--;
							double gall = 0;
							for (int k = j; k <= temp; k++) {
								gall+=k;
							}
							nb = nb+(double)(gall)/(temp-j+1)+1;
							break;
						}
						if (x[temp]==x[j]) {
							temp++;
						}else{
							temp--;
							double gall = 0;
							for (int k = j; k <= temp; k++) {
								gall+=k;
							}
							nb = nb+(double)(gall)/(temp-j+1)+1;
							break;
						}
					}
					break;
				}
			}
		}
		//System.out.println(na+"         "+nb);
		double all= 0;
		for (int i = 1; i <= x.length; i++) {
			all = all+i;
		}
		
		//System.out.println(all);
		//System.out.println((double)na/all);
		//且na和nb均大于10，总体样本符合正态分布
		double u = (double)a.length*(a.length+b.length+1)/2;
		double oo = (double)a.length*b.length*(a.length+b.length+1)/12;
		
		asa = FenBuFunction.zhengtai(asa);
		//System.out.println(u);
		//System.out.println(asa+"         "+Math.abs((na - 120)/Math.sqrt(oo)));
		
		return asa<=Math.abs((na - u)/Math.sqrt(oo));
	}
	
	
	
	/******************方差分析以及回归分析12。。。。。。。。。。。。。。。没有完全做完***************************/
	
	/**
	 * 相关系数检验
	 * 
	 * 
	 * @param t	置信度
	 * @param n	样本总量
	 * @param r	相关系数
	 * @return false为拒绝零假设,（绝零假设为不相关）
	 * double r = 0.926;
		//System.out.println(xiangguanxishujianyan(0.95, 8, r));
	 */

	public static boolean xiangguanxishujianyan(double t,int n,double r){
		
		double tfengbu = FenBuFunction.tfengbu(t, (n-2));
		double asa = r/Math.sqrt((1-r*r)/(n-2));
		//System.out.println(asa+"        "+tfengbu);
		return asa<tfengbu;
	}
	
	
	/**
	 * 一元线性回归模型
	 * x和y的数据要一一对应
	 * 
	 * @param x	样本x
	 * @param y	样本y
	 * 
	 * y = bx + a
	 * @return
	 * 	double[] x = {1,2,3,4};
		double[] y = {6,5,7,10};
		xianxinghuigui(x, y);
	 */

	public static double[] xianxinghuigui(double[] x,double[] y){
		double b;
		double averagex = TUtils1.average(x);
		double averagey = TUtils1.average(y);
		double one = 0;
		double two = 0;

		for (int i = 0; i < y.length; i++) {
			one= one + (x[i] - averagex)*(y[i]-averagey);
		}
		for (int i = 0; i < y.length; i++) {
			two = two + (x[i] - averagex)* (x[i] - averagex);
		}

		b = one/two;
		double a = averagey - b*averagex;
		//System.out.println(a+"          "+b);
		double[] asa = new double[2];
		asa[0] = a;
		asa[1] = b;
		return asa;
		
	}
	/**
	 * 回归系数显著性检验b
	 * @return 
	 * 
	 * false为拒绝0假设，false才靠谱
	 * 
	 */
	
	public static boolean huiguixishuxianzhuxingjianyana(double[] x,double[] y,double t){
		double averagex = TUtils1.average(x);
		double averagey = TUtils1.average(y);
		double one = 0;
		double two = 0;

		for (int i = 0; i < y.length; i++) {
			one= one + (x[i] - averagex)*(y[i]-averagey);
		}
		for (int i = 0; i < y.length; i++) {
			two = two + (x[i] - averagex)* (x[i] - averagex);
		}

		double b = one/two;
		double a = averagey - b*averagex;
		for (int i = 0; i < y.length; i++) {
			two = two + (x[i] - averagex)* (x[i] - averagex);
		}
		
		double sse = 0;
		for (int i = 0; i < y.length; i++) {
			double temp = x[i]*b+a;
			sse = sse + (y[i] - temp)* (y[i] - temp);
		}
		
		double mse = sse/(y.length-2);
		//b的样本方差
		double ssb = mse/two;
		
		double all = a / Math.sqrt(ssb);
		double asa = FenBuFunction.tfengbu(t, y.length-2);
//		//System.out.println(all+"                "+asa);
		return all < asa;
		
	}
	
	/**
	 * 回归系数显著性检验a
	 * @return 
	 * 
	 * false为拒绝0假设，false才靠谱
	 * 如果这里有问题，看看是不是a和b搞混了
	 */
	
	public static boolean huiguixishuxianzhuxingjianyanb(double[] x,double[] y,double t){
		double averagex = TUtils1.average(x);
		double averagey = TUtils1.average(y);
		double one = 0;
		double two = 0;

		for (int i = 0; i < y.length; i++) {
			one= one + (x[i] - averagex)*(y[i]-averagey);
		}
		for (int i = 0; i < y.length; i++) {
			two = two + (x[i] - averagex)* (x[i] - averagex);
		}

		double b = one/two;
		double a = averagey - b*averagex;
		for (int i = 0; i < y.length; i++) {
			two = two + (x[i] - averagex)* (x[i] - averagex);
		}
		
		double sse = 0;
		for (int i = 0; i < y.length; i++) {
			sse = sse + (x[i] - averagex)* (x[i] - averagex);
		}
		
		double mse = sse/(y.length-2);
		//b的样本方差
		double ssa = mse*((double)1/x.length+averagex*averagex/two);
		
		double all = Math.abs((b - averagex) / Math.sqrt(ssa));
		double asa = FenBuFunction.tfengbu(t, x.length-2);
//		//System.out.println(all+"                "+asa);
		return all < asa;
		
	}
	
	/**
	 * 方差分析，判断组间有没有差异
	 * 要求：
	 * 1。 各个总体是近似正态分布的
	 * 2， 各个总体具有相等的方差
	 * 3. 样本是随机样本
	 * 4. 各个样本间相互独立
	 * 5. 单因素试验
	 * 
	 * 
	 * 他这个分析要将数据分解成很多组，很是奇怪
	 * @return 
	 * @throws Exception 
	 */
	
	public static double[] dangyinsufangchafenxi(double[][] x) throws Exception{
		//sa 因素A 
		//se 误差
		//st 总和
		double st = 0;
		double xij = 0;
		double xavall = 0;
		for (int i = 0; i < x.length; i++) {
			for (int j = 0; j < x[i].length; j++) {
				xij += x[i][j]*x[i][j];
				xavall += x[i][j];
			}
		}
		
		st = xij - (x.length*x[0].length)*Math.pow(xavall/(x.length*x[0].length), 2);
		
		double xoj = 0;
		for (int i = 0; i < x.length; i++) {
			double xj = 0;
			for (int j = 0; j < x[i].length; j++) {
				xj += x[i][j];
			}
			
			xoj += x[i].length*Math.pow(xj/x[i].length, 2); 
		}
		
		
		double sa =xoj - (x.length*x[0].length)*Math.pow(xavall/(x.length*x[0].length), 2);
		double se = st - sa;
		
		double[] asa = new double[3];
		asa[0] = st;
		asa[1] = sa;
		asa[2] = se;
		
		//System.out.println("因素："+sa+"	误差："+se+"	总和："+st);
		
		//f比	f分布F(s-1,n-s) f=(sa/(s-1))/(se/(n-s)),这个n是组数，s是组样本数
		int s = x[0].length;
		int n = x.length;
		double f = (sa/(s-1))/(se/(n-s));
		 double[] ffengbu = FenBuFunction.ffengbu(0.05, s-1, n-s);
		boolean sss = f<ffengbu[0];//true为有差别
		
		return asa;
		
	}
	
	
	
	/**
	 * 方差分析，多因素
	 * 
	 */
	public static double[] dangyinsufangchaduoyingsufenxi(double[][][] x) throws Exception{
		
		int r = x.length;
		int s;
		
		double[][] asa = new double [x.length][];
		for (int i = 0; i < x.length; i++) {
			asa[i] = new double[x[i].length];
			for (int j = 0; j < x[i].length; j++) {
				for (int k = 0; k < x[i][j].length; k++) {
					asa[i][j]+= x[i][j][k];
				}
				asa[i][j] = asa[i][j]/x[i][j].length;
			}
		}
		
		
		
		
		double allu = 0;
		double[] iu = null;
		double[] ju = null;
		for (int i = 0; i < asa.length; i++) {
			iu = new double[asa.length];
			for (int j = 0; j < asa[i].length; j++) {
				iu[i]+= asa[i][j];
			}
			iu[i] = iu[i]/asa[i].length;
		}
		for (int j = 0; j < asa.length; j++) {
			ju = new double[asa[0].length];
			for (int i = 0; i < asa[j].length; i++) {
				ju[j]+= asa[i][j];
			}
			ju[j] = ju[j]/asa.length;
		}
		
		
		for (int i = 0; i < iu.length; i++) {
			allu += iu[i];
		}
		allu = allu/iu.length;
		
		
		double[] a = new double[iu.length];
		double[] b = new double[ju.length];
		
		for (int i = 0; i < a.length; i++) {
			a[i] = iu[i] - allu;
		}
		for (int i = 0; i < b.length; i++) {
			b[i] = ju[i] - allu;
		}
		
		//交互效应值
//		rij = asa[i][j]-iu[i]-ju[j]+allu;
		double[][] rij = new double[asa.length][asa[0].length];
		for (int i = 0; i < rij.length; i++) {
			for (int j = 0; j < rij.length; j++) {
				rij[i][j] = asa[i][j]-iu[i]-ju[j]+allu;
			}
		}
		
		//做双因素实验方差分析，需要检验以下3个假设
		/**
		 * 1，数组a 全为0或不全为0
		 * 2，数组b，全为0或不全为0
		 * 3，数组rij，全为0或不全为0
		 */
		//总和
		double st = 0;
		for (int i = 0; i < x.length; i++) {
			for (int j = 0; j < x[i].length; j++) {
				for (int k = 0; k < x[i][j].length; k++) {
					st+= Math.pow(x[i][j][k] - allu,2);
				}
			}
		}
		//误差
		double se = 0;
		for (int i = 0; i < x.length; i++) {
			for (int j = 0; j < x[i].length; j++) {
				for (int k = 0; k < x[i][j].length; k++) {
					se+= Math.pow(x[i][j][k] - asa[i][j],2);
				}
			}
		}
		
		//因素A
		double sa = 0;
		for (int i = 0; i < iu.length; i++) {
			se+= Math.pow(iu[i] - allu,2);
		}
		sa = x[0].length*x[0][0].length*sa;
		
		//因素B
		double sb = 0;
		for (int i = 0; i < ju.length; i++) {
			se+= Math.pow(ju[i] - allu,2);
		}
		sb = x.length*x[0][0].length*sb;
		//交互作用
		double sab = 0;
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				sab = (asa[i][j]-iu[i]-iu[j]+allu);
			}
		}
		sab = x[0][0].length*sab;
		
		st = se + sa +sb +sab;
		
		
		double sa1 = sa/(x.length-1);
		double sb1 = sb/(x[0].length-1);
		double sab1 = sab/((x.length-1)*(x[0].length-1));
		double se1 = se/(x.length*x[0].length*(x[0][0].length-1));
		
		double fa = sa1/se1;//自由度(x.length-1);
		double fb = sb1/se1;//自由度(x[0].length-1);
		double fab = sab1/se1;//自由度x.length*x[0].length
		
		//对应上面的f查表 总的为误差自由度
		return null;
	}
	
	/******************一元线性回归***********************/
	
	
	
	

	public static void main(String[] args) throws Exception {
		
//		double[] x = {1,2,3,4};
//		double[] y = {6,5,7,10};
//		huiguixishuxianzhuxingjianyanb(x, y, 0.95);
		
		//System.out.println(Math.pow(2, 6));
		
	}
	
	
	
	
}
